#include "SpaceInvadersPCH.h"
#include "Player.h"
#include "WeaponManager.h"

static const float c_maxVelocity = 2.0f;
static const float c_maxThrust = 0.5f;
static const float c_inertia = 0.95f;
static const float c_thrust = 0.01f;
static const float c_xBoundary = 120.0f;
static const float c_thrustRotationCoefficient = 3.5f;
static const float c_randomMovementAmplitude = 0.5f;
static const float c_randomMovementSpeed = 0.02f;
static const float c_fireScaler = 2.0f;
static const float c_weaponReenableTimerDelta = 0.25f;
static const float c_collisionRestitution = 0.75f;
static const cr::uint32_t g_hsShipName = spaceinvaders::prehash::hs_Ship1;

void Player::Initialise()
{
	RequestData(g_hsShipName);

	m_curPlayerX = 0.0f;
	m_curThrust = 0.0f;
	m_curVelocity = 0.0f;
	m_randomMovementTimer = 1;
	m_weaponReenableCounter = 0.0f;
}

void Player::Shutdown()
{
	ReleaseData();
}

void Player::Step()
{
	bool requestFire = false;
	m_curThrust *= 0.9f;
	if (pf::GetPlatform()->GetKeyboard()->GetKeyDown(pf::KeyboardButton::Key_A))
		m_curThrust -= 0.02f;
	else if (pf::GetPlatform()->GetKeyboard()->GetKeyDown(pf::KeyboardButton::Key_D))
		m_curThrust += 0.02f;
	
	if (pf::GetPlatform()->GetKeyboard()->GetKeyDown(pf::KeyboardButton::Key_Space))
		requestFire = true;

	m_curThrust = cr::Maths::Min(m_curThrust, c_maxThrust);
	m_curThrust = cr::Maths::Max(m_curThrust, -c_maxThrust);

	m_curVelocity *= c_inertia;
	m_curVelocity += m_curThrust;

	m_curVelocity = cr::Maths::Min(m_curVelocity, c_maxVelocity);
	m_curVelocity = cr::Maths::Max(m_curVelocity, -c_maxVelocity);

	m_curPlayerX += m_curVelocity;

	if (m_curPlayerX < -c_xBoundary)
	{
		m_curPlayerX = -c_xBoundary;
		m_curVelocity = -m_curVelocity * c_collisionRestitution;
		m_curThrust = -m_curThrust;
	}
	else if (m_curPlayerX > c_xBoundary)
	{
		m_curPlayerX = c_xBoundary;
		m_curVelocity = -m_curVelocity * c_collisionRestitution;
		m_curThrust = -m_curThrust;
	}

	m_weaponReenableCounter = cr::Maths::Max(0.0f, m_weaponReenableCounter - c_weaponReenableTimerDelta);
	float scaler = 1.0f;
	if (requestFire)
	{
		scaler = c_fireScaler;
		if (m_weaponReenableCounter == 0)
		{
			WeaponManager::Get().AddBullets(cr::Vec4f(m_curPlayerX, 3.0f, 0.0f,0.0f));
			m_weaponReenableCounter = 1.0f;
		}
	}

	// Update random movement
	m_randomMovementTimer-=c_randomMovementSpeed*scaler;
	if(m_randomMovementTimer < 0)
	{
		float xT = ((((float)rand() / (float)RAND_MAX)*2.0f)-1.0f);
		float yT = ((((float)rand() / (float)RAND_MAX)*2.0f)-1.0f);
		float zT = 0.0f;
		m_randomOffset = cr::Vec4f(xT*c_randomMovementAmplitude, yT*c_randomMovementAmplitude, zT*c_randomMovementAmplitude,0);
		m_randomMovementTimer = 1.0f;
	}
}

void Player::Draw(DrawContext& drawContext)
{
	if (m_pRenderData)
	{
		gp::ParameterBlockScratch<1> params;
		cr::Matrix4f shipTransform = cr::Matrix4f::RotZ(-m_curThrust * c_thrustRotationCoefficient);
		shipTransform.m_translation.setX(m_curPlayerX);
		shipTransform.m_translation.setY(3.0f);
		shipTransform.m_translation += m_randomOffset.scale3(sinf(m_randomMovementTimer*cr::Maths::kPI));
		params.AddParameter()->Set(spaceinvaders::prehash::hs_g_objectToWorld, spaceinvaders::prehash::hs_OBJECTTOWORLD, gk::GpuProgramParameterType::Matrix, shipTransform);
		drawContext.PushParameterBlock(params);
		drawContext.DrawModels(m_pRenderData);
		drawContext.PopParameterBlock();
	}
}